–traffic-sign-detection

前言


終於來到 project 2 了, 這次的主要目的是練習使用 tensorflow 做交通號誌識別
Dataset 為 German Traffic Sign Dataset
有43種交通號誌, 是一種43選1的概念, 因為沒有考慮都不是這個選項, 理論上這類問題較簡單, 有researcher達到99.81%的辨識率

共 51839 張 training data, 而 testing 有 12630 張, 分佈如下, 可以看的出來資料分佈不均
data-distribution
每種類別 random 挑一張出來如下圖
43-classes
Udacity 很好心的幫忙把所有的 image 幫你打包成只剩下 traffic sign Download, 且 cv2.resize(image,(32,32)) 了, 只需要 pickle.load 下來就搞定
而原始的 data 是給你一大張image, 然後再告訴你那些traffic signs在image中的rectangular window座標, 還要再多處理較麻煩

要注意的一點是, dataset 是經由一秒鐘的 video 擷取下來, 因此鄰近的 data 會很相近 [1], 如果使用 train_test_split 會 random 選擇, 導致 train 和 validation 會相近而看不出差異

Input Data Preprocessing

Udacity 建議我們可以處理幾個方向

  1. 將 data 數量弄得較 balance
    NN 算 loss 的時候不會根據每個類別數量的多寡作權重, 因此最單純的方法是就想辦法產生出一樣多的數量, 如第2點
  2. 可以增加 fake data
    我的 image processing 實在很弱, 只單純的使用 rotation, 而且只敢稍微讓angle為正負5度, 怕那種有方向箭頭的號誌轉壞

    1
    cv2.getRotationMatrix2D(image_center, angle, scale)

    這樣的方式我實驗起來其實沒啥幫助, XD
    我看到有人還使用 cv2.WarpPerspective, 果然專業多了! 我相信產生種類夠多的 fake data 一定會有幫助, 例如加 noise, blur 等等

  3. 將 data 做 normalization
    做語音習慣了, 直覺就用 guassian normalization, mean=0, var=1, 結果整個大失敗! 只有不到1%辨識率, why??
    後來用 mean substraction, 然後除 abs 的最大值, 我只選擇使用 YUV 的 Y channel 當 input

CNN 架構

要設計和調整架構有點花時間, 加上我時間不多(), 所以我直接就用LeNet架構

1
2
3
4
5
6
7
layer_depth = {
'layer_1': 6,
'layer_2': 16,
'fully_connected_1': 120,
'fully_connected_2': 84,
'out': n_classes,
}

自己多加了 dropoutl2 regularization, 原因是每次跑 training 的 accuracy 都要標到98 99, 但是 validation set 始終很難突破 93, 一直有 overfit 的感覺
tensorflow 的 dropout 是設定要保留多少比例 (keep_prob), 在 training 的時候設定在最後的兩層 fully connected layers, keep_prob 愈小基本上愈難訓練也需要愈多 epoch
另外記得在做 evaluation 的時候要把 keep_prob 設定成回 1

[1] 的架構想法不錯, 將較低層的 conv. layer 和較上層的 conv. layer 一併當作 fully connected layer 的 input, 這樣同時能夠有 low-level feature, higher-resolution 和 high-level feature, lower-resolution 兩種資訊一起當決策
Traffic-sign-CNN

其他 Hyper-parameters

  • Optimizer: 說實話, 要不停的調整出最好的參數實在沒那個心力, 所以與其用SGD, 我就直接用 Adam 了 (Adagrad也是一種懶人選擇)
  • pooling: 沒啥特別選, 因此用 max-pooling
  • batch-size: 原先設定128, 有一次改成256就實在train不好, 就退回128了
  • learning rate: 0.001
  • l2 weight: 0.01

Learning Performance

train_validation_performance
test set accuracy = 0.893

自選測試圖片

Udacity希望能學員自己找圖片來測試, 因此我就在德國的 google map 上找圖, (看著看著心都飄過去了)
20-test-from-google-map
20張圖辨識結果如下:
from_google_map_performance
剛好錯10個, 只有 50% 正確率, 這實在有點悲劇
其中有兩個錯誤值得注意
error_traffic_signal
右圖是top5辨識到的類別及機率, 可以發現除了正確答案的 traffic signal 在第二名外, 第一名的 general causion 其實跟 traffic signal 超像的 (只看灰階)
看來必須把 input 的色彩資訊也加進去才能進一步改善了
另一個是如下
error_speed_limit_30
這個錯誤自己分析的原因是因為 training data 的 speed limit 都是圓的外框, 而此case剛好是一個長方形牌子, 裡面才是退色很嚴重的圓形, 所以導致辨識失敗
或許真的 train 得很好的 CNN 有能力找出重要的判斷資訊, 因此會去忽略外面的方框, 而選擇去”看”外面退色的圓形和裡面的數字
結論就是, 應該是我自己沒train好吧 ?!

短結

小小做過一輪交通號誌辨識, 才比較有感覺真實狀況會有多困難阿~
找時間來 visualize 一下每層的 hidden units 對什麼樣的 image 會有較高的 activation! This paper by Zeiler and Fergus with toolbox

要能 train 出好 model 除了參考文獻培養對 model 架構的好直覺外, engineering 的苦工也會是很大的關鍵!

後續嘗試

對於目前的辨識率很不滿意. 不死心下就實作[1]的架構, 然後將 NN 的 model size 擴大, 並且將顏色資訊 YUV 的 U 加進去訓練 (結果上述因顏色錯誤的traffic signal就分對了)

1
2
3
4
5
6
7
8
9
10
11
12
13
# Hyper-parameters
EPOCHS = 30
BATCH_SIZE = 128
rate = 0.001
drop_out_keep_prob = 0.5
layer_depth = {
'layer_1': 16,
'layer_2': 32,
'fully_connected_1': 256,
'fully_connected_2': 128,
'out': n_classes,
}

得到了 Test Accuracy = 0.953 ! 但是自選圖雖有進步仍很低 65%
另外, 上述的參數設定下, 如果加了 l2_weight = 0.01 的話, validation 只能到 0.91x, 實在不大好訓練, 後來只好放棄
第一次的 submission, reviewer 給了一些不錯的 reference 如下:

Extra Important Material

Lately on slack few students asked for a good Deep Learning book.So after lot of research found a book which is also recommended by Elon Musk

reviewer 很用心阿!棒棒!


Reference

[1.] Traffic Sign Recognition with Multi-Scale Convolutional Networks